package com.hosever.coreTest2;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class RandomFileTest {  
    public static void main(String[] args) {  
        Employee[] staff = new Employee[3];  
  
        staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);  
        staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);  
        staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);  
  
        try {  
            // save all employee records to the file employee.dat  
            DataOutputStream out = new DataOutputStream(new FileOutputStream("employee.dat"));  
            for (Employee e : staff)  
                e.writeData(out);  
            out.close();  
  
            // retrieve all records into a new array  
            RandomAccessFile in = new RandomAccessFile("employee.dat", "r");  
            // compute the array size  
            int n = (int) (in.length() / Employee.RECORD_SIZE);  
            Employee[] newStaff = new Employee[n];  
  
            // read employees in reverse order  
            for (int i = n - 1; i >= 0; i--) {  
                newStaff[i] = new Employee();  
                in.seek(i * Employee.RECORD_SIZE);  
                newStaff[i].readData(in);  
            }  
            in.close();  
  
            // print the newly read employee records  
            for (Employee e : newStaff)  
                System.out.println(e);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  
  
class Employee {  
    public Employee() {  
    }  
  
    public Employee(String n, double s, int year, int month, int day) {  
        name = n;  
        salary = s;  
        GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);  
        hireDay = calendar.getTime();  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public double getSalary() {  
        return salary;  
    }  
  
    public Date getHireDay() {  
        return hireDay;  
    }  
  
    /** 
     * Raises the salary of this employee. 
     *  
     * @byPercent the percentage of the raise 
     */  
    public void raiseSalary(double byPercent) {  
        double raise = salary * byPercent / 100;  
        salary += raise;  
    }  
  
    public String toString() {  
        return getClass().getName() + "[name=" + name + ",salary=" + salary  
                + ",hireDay=" + hireDay + "]";  
    }  
    /** 
     * Writes employee data to a data output(固定大小) 
     * @param out the data output 
     * @throws IOException 
     */  
    public void writeData(DataOutput out) throws IOException {  
        DataIO.writeFixedString(name, NAME_SIZE, out);  
        out.writeDouble(salary);  
  
        GregorianCalendar calendar = new GregorianCalendar();  
        calendar.setTime(hireDay);  
        out.writeInt(calendar.get(Calendar.YEAR));  
        out.writeInt(calendar.get(Calendar.MONTH) + 1);  
        out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));  
    }  
  
    /** 
     * Reads employee data from a data input 
     * (每条记录大小一样) 
     * @param in 
     *            the data input 
     */  
    public void readData(DataInput in) throws IOException {  
        name = DataIO.readFixedString(NAME_SIZE, in);  
        salary = in.readDouble();  
        int y = in.readInt();  
        int m = in.readInt();  
        int d = in.readInt();  
        GregorianCalendar calendar = new GregorianCalendar(y, m - 1, d);  
        hireDay = calendar.getTime();  
    }  
   /* 
    * 使用40个字符来表示名字字符串,所以每条记录是100字节 
    * 40字符  =  80字节(名字) 
    * 1 double = 8字节(薪水) 
    * 3 int = 12字节(日期) 
    */  
   public static final int NAME_SIZE = 40;  
   public static final int RECORD_SIZE = 2 * NAME_SIZE + 8 + 4 + 4 + 4;//(String,double,int,int,int)  
  
   private String name;  
   private double salary;  
   private Date hireDay;  
}  
  
class DataIO {  
    /** 
     * 从输入流中读入字符 
     * @param size 长度 
     * @param in 
     * @return 
     * @throws IOException 
     */  
    public static String readFixedString(int size, DataInput in)  
            throws IOException {  
        StringBuilder b = new StringBuilder(size);  
        int i = 0;  
        boolean more = true;  
        while (more && i < size) {  
            char ch = in.readChar();  
            i++;  
            if (ch == 0)  
                more = false;  
            else  
                b.append(ch);  
        }  
        in.skipBytes(2 * (size - i));  
        return b.toString();  
    }  
    /** 
     * 读写具有固定大小的字符串 
     * @param s 
     * @param size 
     * @param out 
     * @throws IOException 
     */  
    public static void writeFixedString(String s, int size, DataOutput out)  
            throws IOException {  
        for (int i = 0; i < size; i++) {  
            char ch = 0;  
            if (i < s.length())  
                ch = s.charAt(i);  
            out.writeChar(ch);  
        }  
    }  
}  
